package cn.wei.youvie.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.wei.youvie.common.constant.CommonConstant;
import cn.wei.youvie.common.exception.BusinessException;
import cn.wei.youvie.common.exception.ThrowUtils;
import cn.wei.youvie.common.servlet.DeleteRequest;
import cn.wei.youvie.common.servlet.ErrorCode;
import cn.wei.youvie.domain.dto.book.BookAddRequest;
import cn.wei.youvie.domain.dto.book.BookQueryRequest;
import cn.wei.youvie.domain.dto.book.BookUpdateRequest;
import cn.wei.youvie.domain.dto.chapter.ChapterAddRequest;
import cn.wei.youvie.domain.dto.content.ContentAddRequest;
import cn.wei.youvie.domain.dto.section.SectionAddRequest;
import cn.wei.youvie.domain.entity.User;
import cn.wei.youvie.domain.vo.BookVO;
import cn.wei.youvie.service.*;
import cn.wei.youvie.utils.SqlUtils;
import cn.wei.youvie.utils.WordUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.wei.youvie.domain.entity.Book;
import cn.wei.youvie.mapper.BooksMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author Youvie
* @description 针对表【books(存储书籍的基本信息)】的数据库操作Service实现
* @createDate 2024-08-27 21:02:05
*/
@Service
public class BookServiceImpl extends ServiceImpl<BooksMapper, Book>
    implements BookService {

    @Autowired
    private UserService userService;

    @Autowired
    private BooksMapper booksMapper;

    @Autowired
    private ChapterService chapterService;

    @Autowired
    private SectionService sectionService;

    @Autowired
    private ContentService contentService;

    @Override
    public Integer add(BookAddRequest booksAddRequest, HttpServletRequest request) {
        if (booksAddRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Book book = new Book();
        BeanUtils.copyProperties(booksAddRequest, book);

        //添加当前用户信息
        User loginUser = userService.getLoginUser(request);
        book.setUserId(loginUser.getId());

        boolean saved = this.save(book);
        ThrowUtils.throwIf(!saved, ErrorCode.OPERATION_ERROR);
        return book.getBookId();
    }

    @Override
    public boolean deleteBook(DeleteRequest deleteRequest, HttpServletRequest request) {
        if (deleteRequest == null || deleteRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User user = userService.getLoginUser(request);
        long id = deleteRequest.getId();
        // 判断是否存在
        Book oldBook = this.getById(id);
        ThrowUtils.throwIf(oldBook == null, ErrorCode.NOT_FOUND_ERROR);
        // 仅本人或管理员可删除
        if (!oldBook.getUserId().equals(user.getId()) && !userService.isAdmin(request)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        return this.removeById(id);
    }

    @Override
    public boolean updateBook(BookUpdateRequest booksUpdateRequest) {
        Book book = new Book();
        BeanUtils.copyProperties(booksUpdateRequest, book);
        long id = booksUpdateRequest.getBookId();
        // 判断是否存在
        Book oldBook = this.getById(id);
        ThrowUtils.throwIf(oldBook == null, ErrorCode.NOT_FOUND_ERROR);
        return this.updateById(book);
    }

    @Override
    public BookVO getBookVO(Book book, HttpServletRequest request) {
        BookVO bookVO = new BookVO();
        BeanUtils.copyProperties(book, bookVO);
        return bookVO;
    }

    @Override
    public Wrapper<Book> getQueryWrapper(BookQueryRequest booksQueryRequest) {
        Long userId = booksQueryRequest.getUserId();
        String sortField = booksQueryRequest.getSortField();
        String sortOrder = booksQueryRequest.getSortOrder();
        String searchText = booksQueryRequest.getSearchText();

        QueryWrapper<Book> bookQueryWrapper = new QueryWrapper<>();
        if (searchText != null) {
            bookQueryWrapper.and(qw -> qw.like("title", searchText)
                    .or().like("author", searchText)
                    .or().like("description", searchText)
                    .or().like("genre", searchText)
            );
        }
        bookQueryWrapper.eq("user_id", userId);
        bookQueryWrapper.orderBy(SqlUtils.validSortField(sortField),
                sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                sortField);
        return bookQueryWrapper;
    }

    @Override
    public Page<BookVO> getBookVOPage(Page<Book> booksPage, HttpServletRequest request) {
        List<Book> bookList = booksPage.getRecords();
        Page<BookVO> postVOPage = new Page<>(booksPage.getCurrent(), booksPage.getSize(), booksPage.getTotal());
        if (CollUtil.isEmpty(bookList)) {
            return postVOPage;
        }

        // 填充信息
        List<BookVO> postVOList = bookList.stream()
                .map(BookVO::objToVo)
                .collect(Collectors.toList());

        postVOPage.setRecords(postVOList);
        return postVOPage;
    }

    @Override
    public Book getBookBySectionId(Integer sectionId) {
        return booksMapper.getBookBySectionId(sectionId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertContentOfFile(MultipartFile file, HttpServletRequest request, int bookId) {
        // 当前登录账号是否是书本的创建人
        User loginUser = userService.getLoginUser(request);
        Book book = this.getById(bookId);
        if (!loginUser.getId().equals(book.getUserId())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }

        // 读取word文档的内容并持久化
        try (InputStream inputStream = file.getInputStream()) {
            String fileName = file.getOriginalFilename(); // 获取原始文件名
            ThrowUtils.throwIf(fileName == null, ErrorCode.PARAMS_ERROR);
            if (fileName.endsWith(".docx")) {
                List<XWPFParagraph> xwpfParagraphs = WordUtils.readDocx(inputStream);
                handleBookOfDocx(xwpfParagraphs, bookId, request);
            } else if (fileName.endsWith(".doc")) {
                // todo doc文件待实现
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "doc文件格式不支持");
            } else {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "文件格式不支持");
            }
            return true;
        } catch (IOException e) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "文件读取异常");
        }
    }

    public void handleBookOfDocx(List<XWPFParagraph> paragraphs, int bookId, HttpServletRequest request) {
        ChapterAddRequest chapterAddRequest = new ChapterAddRequest();
        chapterAddRequest.setBookId(bookId);
        int chapterNum = 0;
        int sectionNum = 0;
        int currentChapterId = 0;

        // 循环段落构建书本类
        for (XWPFParagraph paragraph : paragraphs) {
            String style = paragraph.getStyle();
            String text = paragraph.getText();

            if (StringUtils.isBlank(text)) {
                continue;
            }
            try {
                if (style != null && Integer.parseInt(style) < 5) { // 添加新章节
                    chapterAddRequest.setChapterNumber(chapterNum);
                    chapterNum += 5;
                    chapterAddRequest.setTitle(text);
                    currentChapterId = chapterService.add(chapterAddRequest, request);
                } else { // 添加新段落
                    SectionAddRequest sectionAddRequest = new SectionAddRequest();
                    sectionAddRequest.setChapterId(currentChapterId);
                    sectionAddRequest.setSectionNumber(sectionNum);
                    sectionNum += 5;
                    Integer sectionId = sectionService.add(sectionAddRequest, request);

                    ContentAddRequest contentAddRequest = new ContentAddRequest();
                    contentAddRequest.setSectionId(sectionId);
                    contentAddRequest.setText(text);
                    Integer contentId = contentService.add(contentAddRequest, request);
                    if (contentId <= 0) { // 修改逻辑判断条件
                        throw new BusinessException(ErrorCode.OPERATION_ERROR, "内容插入失败");
                    }
                }
            } catch (NumberFormatException e) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "样式格式错误");
            }
        }
    }
}




